package renpyas3.view 
{
	import flash.utils.Dictionary;
	import org.osflash.thunderbolt.Logger;
	import renpyas3.model.RenpyPlayerModel;
	import renpyas3.model.structs.LabelBlockInstruction;
	import renpyas3.view.instructions.ViewInstruction;
	import renpyas3.view.instructions.ViewInstruction_ifOperator;
	import renpyas3.view.instructions.ViewInstruction_jump;
	import renpyas3.view.instructions.ViewInstruction_menu;
	import renpyas3.view.instructions.ViewInstruction_playMusic;
	import renpyas3.view.instructions.ViewInstruction_return;
	import renpyas3.view.instructions.ViewInstruction_scene;
	import renpyas3.view.instructions.ViewInstruction_show;
	import renpyas3.view.instructions.ViewInstruction_textFromChar;
	import renpyas3.view.instructions.ViewInstruction_textFromNarrator;
	import renpyas3.view.instructions.ViewInstruction_varChange;
	
	import flash.utils.getDefinitionByName;
	
	/**
	 * Dictionary for all the view events. Instances instruction classes 
	 * from text commands
	 */
	public class RenpyPlayerInstructionsProcessor
	{
		private var _view:RenpyPlayer;		
		private var _model:RenpyPlayerModel;
		
		private var _viewInstructionsDictionary:Dictionary;
		private var _currInstructionInstance:ViewInstruction;
		private var _currentInstructionDef:LabelBlockInstruction;
		
		public function RenpyPlayerInstructionsProcessor(viewPtr:RenpyPlayer, modelPtr:RenpyPlayerModel)
		{
			_view = viewPtr;
			_model = modelPtr;		
			
			//create instruction commands dictionary
			createDictionary();	
		}
		
		/**
		 * create view instructions dictionary to keep class names
		 * of all the possible view commands
		 */
		private function createDictionary():void
		{
			var ViewInstructionsPath:String = "renpyas3.view.instructions.";
			_viewInstructionsDictionary = new Dictionary();
			_viewInstructionsDictionary[ViewInstruction_ifOperator.NAME] = ViewInstructionsPath + "ViewInstruction_ifOperator";
			_viewInstructionsDictionary[ViewInstruction_jump.NAME] = ViewInstructionsPath + "ViewInstruction_jump";
			_viewInstructionsDictionary[ViewInstruction_menu.NAME] = ViewInstructionsPath + "ViewInstruction_menu";
			_viewInstructionsDictionary[ViewInstruction_playMusic.NAME] = ViewInstructionsPath + "ViewInstruction_playMusic";
			_viewInstructionsDictionary[ViewInstruction_return.NAME] = ViewInstructionsPath + "ViewInstruction_return";
			_viewInstructionsDictionary[ViewInstruction_scene.NAME] = ViewInstructionsPath + "ViewInstruction_scene";
			_viewInstructionsDictionary[ViewInstruction_show.NAME] = ViewInstructionsPath + "ViewInstruction_show";
			_viewInstructionsDictionary[ViewInstruction_textFromChar.NAME] = ViewInstructionsPath + "ViewInstruction_textFromChar";
			_viewInstructionsDictionary[ViewInstruction_textFromNarrator.NAME] = ViewInstructionsPath + "ViewInstruction_textFromNarrator";
			_viewInstructionsDictionary[ViewInstruction_varChange.NAME] = ViewInstructionsPath + "ViewInstruction_varChange";
		}

		
		/**
		 * every instruction needs to notify the processor
		 * when they finished doing their job
		 */
		public function instructionFinished():void
		{
			_currInstructionInstance = null;
			if(_model.currentLabelBlock != null && _currentInstructionDef != null && _currentInstructionDef.requiresUserInput == false)
			{
				runNextInstruction();
			}
		}
		
		
		/**
		 * get next instructions from model and runs them
		 * stops when the instruction requires user input 
		 * like text that requires click to advance 
		 * or buttons that require click to choose where to jump to
		 */
		public function runNextInstruction():void
		{
			if (_model.currentLabelBlock == null)
			{
				//is because of a 'return' instruction ending the game or ending the screen
				return;
			}
			
			if (_currInstructionInstance != null)
			{
				_currInstructionInstance.abort();
				_currInstructionInstance = null;
			}
			else
			{
				
				_currentInstructionDef = _model.currentLabelBlock.getNextInstruction();

				//if this label block is finished and is not the last one
				if (_currentInstructionDef == null && _model.currentLabelBlock.nextLabelBlockIndex != -1)
				{
					//move on to next block
					_model.jumpToNextLabelBlockInSequence();
					_currentInstructionDef = _model.currentLabelBlock.getNextInstruction();
				}
				
				if (_currentInstructionDef != null)
				{
					instanciateInstruction(_currentInstructionDef); 
				}
			}
		}

		/**
		 * instantiate the corresponding instruction class
		 */
		private function instanciateInstruction(instr:LabelBlockInstruction):void
		{
			Logger.info("RenpyPlayerInstructionsProcessor::instanciateInstruction: "+ instr.name+ ", params:"+ instr.params);
			
			if (_viewInstructionsDictionary[instr.name] == null)
			{
				Logger.info("RenpyPlayerInstructionsProcessor::instanciateInstruction --not recognized view event:"+instr.name);
				return;
			}

			var instructionClass:Object = getDefinitionByName(_viewInstructionsDictionary[instr.name]);
			_currInstructionInstance = new instructionClass();
			_currInstructionInstance.execute(_view,_model,instr.params);
		}
	}
}